home *** CD-ROM | disk | FTP | other *** search
- //////////////////////////////////////////////////////
- // huffdec.cpp: huffman decoder methods huffdec.cpp
- // Copyright (c) 1991 Azarona Software
- // All rights reserved.
- //////////////////////////////////////////////////////
-
- #include <string.h>
- #include "huffdec.h"
-
- int huff_decoder::connect(FILE *f, long locn)
- {
- static char signature[] = "HZIP 1.0";
- fin = f;
-
- fseek(f, locn, SEEK_SET);
- fread(signature, 8, 1, f);
- if (strcmp(signature, "HZIP 1.0")) return 0;
- build_tree(ftell(f));
- text_locn = ftell(f);
- reset();
- return 1;
- }
-
- void huff_decoder::reset(void)
- // Resets cbit, which when decompressing will cause the
- // next data byte to be read.
- {
- cbit = -1;
- }
-
- void huff_decoder::reset(long locn)
- {
- fseek(fin, locn, SEEK_SET);
- reset();
- }
-
- int huff_decoder::get_bits(int nbits)
- // Get next n bits from bitstream
- {
- int i, word = 0;
- for (i = 0; i<nbits; i++) {
- if (cbit < 0) {
- cbyte = get_input_char();
- if (cbyte == -1) return -1;
- cbit = 7;
- }
- word <<= 1; word &= 0xfffe;
- word |= ((cbyte >> cbit--) & 0x0001);
- }
- return word;
- }
-
- int huff_decoder::get_next_char(void)
- // Gets the next uncompressed character by walking the
- // huffman binary coding tree. Returns -1 when all the
- // uncompressed bytes have been returned.
- {
- int r = 0; /* Root starts at zero */
-
- while (1) {
- if (cbit < 0) {
- cbyte = get_input_char();
- if (cbyte == -1) return -1;
- cbit = 7;
- }
- if ((cbyte >> cbit--) & 0x0001)
- r = tree[r].left;
- else r = tree[r].right;
- if (r & 0x100) return r & 0xff; // Return symbol
- }
- }
-
- void huff_decoder::build_tree(long codes_locn)
- // Assumes codes are perfect
- {
- int sym;
- char bit, nbits;
- char *code_lens;
- unsigned *codes, bits;
- int next_avail_node;
- tree_node *cn;
-
- next_avail_node = 0;
-
- fseek(fin, codes_locn, SEEK_SET);
-
- fread(&num_symbols, sizeof(int), 1, fin);
-
- code_lens = new char[num_symbols];
- codes = new unsigned[num_symbols];
-
- fread(codes, sizeof(unsigned), num_symbols, fin);
- fread(code_lens, sizeof(char), num_symbols, fin);
-
- tree = new tree_node[num_symbols];
-
- for (sym = 0; sym < num_symbols; sym++) {
- tree[sym].left = tree[sym].right = -1;
- }
-
- for (sym = 0; sym < num_symbols; sym++) {
- nbits = code_lens[sym];
- bits = codes[sym];
- cn = tree;
- while(nbits) {
- bit = (bits & 0x8000) != 0;
- if (nbits == 1) {
- if (bit) {
- // if (cn->left != -1) printf("oops!\n");
- cn->left = num_symbols + sym;
- }
- else {
- // if (cn->right != -1) printf("oops!\n");
- cn->right = num_symbols + sym;
- }
- }
- else {
- if (bit) {
- if (cn->left == -1) {
- cn->left = ++next_avail_node;
- cn = tree + next_avail_node;
- }
- else {
- cn = tree + cn->left;
- }
- }
- else {
- if (cn->right == -1) {
- cn->right = ++next_avail_node;
- cn = tree + next_avail_node;
- }
- else {
- cn = tree + cn->right;
- }
- }
- }
- bits <<= 1;
- nbits--;
- }
- }
- delete codes;
- delete code_lens;
- }
-